﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Text;

namespace TemplateManager
{
    public class ComplexTemplate : ITemplate
    {
        string projectName = "ComplexWebApplication1";
        string projectPath = @"C:\Template\ComplexWebApplication1\";

        public string ProjectName
        {
            get { return this.projectName; }
            set { throw new NotImplementedException("Cannot set value for this property."); }
        }

        public string ProjectPath
        {
            get { return this.projectPath; }
            set { this.projectPath = value; }
        }

        public string GUID
        {
            get { return ""; }
            set { throw new NotImplementedException("Cannot set value for this property."); }
        }

        private ClassLibTemplate classLibTemplate;

        public ClassLibTemplate ClassLibTemplate
        {
            get
            {
                if (classLibTemplate == null)
                {
                    classLibTemplate = new ClassLibTemplate();
                    classLibTemplate.ProjectPath = ProjectPath + @"ClassLibrary1\";
                }

                return classLibTemplate;
            }
        }

        private WcfTemplate wcfTemplate;

        public WcfTemplate WcfTemplate
        {
            get
            {
                if (wcfTemplate == null)
                {
                    wcfTemplate = new WcfTemplate();
                    wcfTemplate.ProjectPath = ProjectPath + @"WcfService1\";
                }
                return wcfTemplate;
            }
        }

        private Mvc3Template mvc3Template;

        public Mvc3Template Mvc3Template
        {
            get
            {
                if (mvc3Template == null)
                {
                    mvc3Template = new Mvc3Template();
                    mvc3Template.ProjectPath = ProjectPath + @"MvcApplication1\";
                }
                return mvc3Template;
            }
        }

        private IProject classLibProject;
        private IProject wcfProject;
        private IProject mvc3Project;

        public IProject ClassLibProject
        {
            get { return classLibProject; }
            set { classLibProject = value; }
        }

        public IProject WcfProject
        {
            get { return wcfProject; }
            set { wcfProject = value; }
        }

        public IProject Mvc3Project
        {
            get { return mvc3Project; }
            set { mvc3Project = value; }
        }

        private string newSolutionName, newSolutionPath, classLibProjectName, wcfProjectName, mvc3ProjectName;

        IProject ITemplate.CreateNewProject(string ProjectName, string ProjectPath)
        {
            throw new NotImplementedException();
        }

        public IProject CreateNewProject(string newSolutionName, string newSolutionPath,
                            string classLibProjectName, string wcfProjectName, string mvc3ProjectName)
        {
            this.newSolutionName = newSolutionName;
            this.newSolutionPath = newSolutionPath;
            this.classLibProjectName = classLibProjectName;
            this.wcfProjectName = wcfProjectName;
            this.mvc3ProjectName = mvc3ProjectName;

            string newProjectPath = newSolutionPath + newSolutionName + @"\";

            this.classLibProject = this.ClassLibTemplate.CreateNewProject(classLibProjectName, newProjectPath);
            this.wcfProject = this.WcfTemplate.CreateNewProject(wcfProjectName, newProjectPath);
            this.mvc3Project = this.Mvc3Template.CreateNewProject(mvc3ProjectName, newProjectPath);

            RebuildClassLibProject();
            ResolveReferencesInWcfProject("EmployeeService");
            RebuildAndHostWcfProject();
            ResolveReferencesInMvc3Project();

            CopySolutionFile();

            return this;
        }

        public void AddFile(string sourcePath)
        {
            string newProjectPath = newSolutionPath + newSolutionName + @"\";

            this.classLibProject.AddFile(sourcePath + classLibProjectName + @"\");
            this.wcfProject.AddFile(sourcePath + wcfProjectName + @"\");
            this.mvc3Project.AddFile(sourcePath + mvc3ProjectName + @"\");
        }

        private void RebuildClassLibProject()
        {
            ProcessStartInfo p = new ProcessStartInfo();
            p.CreateNoWindow = false;
            p.UseShellExecute = false;
            p.FileName = @"C:\Program Files (x86)\Microsoft Visual Studio 11.0\Common7\IDE\devenv.exe";
            p.WindowStyle = ProcessWindowStyle.Hidden;
            p.Arguments = " /build Debug \"" + this.newSolutionPath + this.newSolutionName + @"\" + this.classLibProject.ProjectName + @"\" + this.classLibProject.ProjectName + ".csproj\""
                        + " /project \"" + this.classLibProject.ProjectName + @"\" + this.classLibProject.ProjectName + ".csproj\"";

            try
            {
                using (Process exeProcess = Process.Start(p))
                {
                    //exeProcess.WaitForExit();
                    exeProcess.Close();
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex);
            }
        }

        private void CopySolutionFile()
        {
            ////Copy .suo
            //if (Directory.Exists(this.projectPath))
            //{
            //    string newFileName;
            //    foreach (string fileName in Directory.GetFiles(this.projectPath))
            //    {
            //        newFileName = newSolutionPath + newSolutionName + "\\" + new FileInfo(fileName).Name.Replace(this.projectName, this.newSolutionName);
            //        File.Copy(fileName, newFileName);
            //        ChangeSolutionFileContent(newFileName);
            //    }
            //}

            //Not Copy .suo
            if (File.Exists(ProjectPath + ProjectName + ".sln"))
                File.Copy(ProjectPath + ProjectName + ".sln",
                    newSolutionPath + newSolutionName + "\\" + newSolutionName + ".sln");

            string temppath = newSolutionPath + newSolutionName + "\\" + newSolutionName + ".sln";
            ChangeSolutionFileContent(temppath);
        }

        private void ChangeSolutionFileContent(string temppath)
        {
            StreamReader reader = new StreamReader(File.OpenRead(temppath));
            string fileContent = reader.ReadToEnd();
            reader.Close();
            File.Delete(temppath);

            fileContent = fileContent.Replace(this.ClassLibTemplate.ProjectName, this.classLibProject.ProjectName);
            fileContent = fileContent.Replace(this.ClassLibTemplate.GUID, this.classLibProject.GUID);

            fileContent = fileContent.Replace(this.WcfTemplate.ProjectName, this.wcfProject.ProjectName);
            fileContent = fileContent.Replace(this.WcfTemplate.GUID, this.wcfProject.GUID);

            fileContent = fileContent.Replace(this.Mvc3Template.ProjectName, this.mvc3Project.ProjectName);
            fileContent = fileContent.Replace(this.Mvc3Template.GUID, this.mvc3Project.GUID);

            StreamWriter writer = new StreamWriter(File.OpenWrite(temppath));
            writer.Write(fileContent);
            writer.Close();
        }

        private void ResolveReferencesInWcfProject(string newServiceName)
        {
            string temppath = newSolutionPath + newSolutionName + "\\" + this.wcfProject.ProjectName + "\\" + this.wcfProject.ProjectName + ".csproj";

            StreamReader reader = new StreamReader(File.OpenRead(temppath));
            string fileContent = reader.ReadToEnd();
            reader.Close();
            File.Delete(temppath);

            fileContent = fileContent.Replace(this.ClassLibTemplate.ProjectName, this.classLibProject.ProjectName);
            fileContent = fileContent.Replace("Service1", newServiceName);

            StreamWriter writer = new StreamWriter(File.OpenWrite(temppath));
            writer.Write(fileContent);
            writer.Close();
        }

        private void RebuildAndHostWcfProject()
        {
            ProcessStartInfo p = new ProcessStartInfo();
            p.CreateNoWindow = false;
            p.UseShellExecute = false;
            p.FileName = @"C:\Program Files (x86)\Microsoft Visual Studio 11.0\Common7\IDE\devenv.exe";
            p.WindowStyle = ProcessWindowStyle.Hidden;
            p.Arguments = " /build Debug \"" + this.newSolutionPath + this.newSolutionName + @"\" + this.wcfProject.ProjectName + @"\" + this.wcfProject.ProjectName + ".csproj\""
                        + " /project \"" + this.wcfProject.ProjectName + @"\" + this.wcfProject.ProjectName + ".csproj\"";

            try
            {
                using (Process exeProcess = Process.Start(p))
                {
                    //exeProcess.WaitForExit();
                    exeProcess.Close();
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex);
            }
        }

        private void ResolveReferencesInMvc3Project()
        {
            string temppath = newSolutionPath + newSolutionName + "\\" + this.mvc3Project.ProjectName + "\\" + this.mvc3Project.ProjectName + ".csproj";

            StreamReader reader = new StreamReader(File.OpenRead(temppath));
            string fileContent = reader.ReadToEnd();
            reader.Close();
            File.Delete(temppath);

            fileContent = fileContent.Replace(this.ClassLibTemplate.ProjectName, this.classLibProject.ProjectName);

            StreamWriter writer = new StreamWriter(File.OpenWrite(temppath));
            writer.Write(fileContent);
            writer.Close();
        }
    }
}
